﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Windows.Media;

namespace Elentok.Common.Wpf.ViewModels.Dialogs
{
  /// <summary>
  /// Defines the wizard dialog view model
  /// </summary>
  public interface IWizardDialogViewModel : IDialogViewModel
  {
    /// <summary>
    /// Gets the next command.
    /// </summary>
    /// <value>The next command.</value>
    ICommand NextCommand { get; }

    /// <summary>
    /// Gets the prev command.
    /// </summary>
    /// <value>The prev command.</value>
    ICommand PrevCommand { get; }

    /// <summary>
    /// Gets the finish command.
    /// </summary>
    /// <value>The finish command.</value>
    ICommand FinishCommand { get; }

    /// <summary>
    /// Gets the current page.
    /// </summary>
    /// <value>The page.</value>
    IWizardPageViewModel Page { get; }
  }

  /// <summary>
  /// Defines the page of a wizard dialog
  /// </summary>
  public interface IWizardPageViewModel : IViewModel
  {
    /// <summary>
    /// Gets the title.
    /// </summary>
    /// <value>The title.</value>
    string Title { get; }
    /// <summary>
    /// Gets the message.
    /// </summary>
    /// <value>The message.</value>
    string Message { get; }
  }

  /// <summary>
  /// The wizard dialog view model
  /// </summary>
  public class WizardDialogViewModel : DialogViewModelBase, IWizardDialogViewModel
  {
    #region Fields

    private IWizardPageViewModel page;
    private List<IWizardPageViewModel> pages = new List<IWizardPageViewModel>();
    #endregion

    #region Ctor

    /// <summary>
    /// Initializes a new instance of the <see cref="WizardDialogViewModel"/> class.
    /// </summary>
    public WizardDialogViewModel()
    {
      this.NextCommand = new DelegateCommand<object>(ExecuteNextCommand, CanExecuteNextCommand);
      this.PrevCommand = new DelegateCommand<object>(ExecutePrevCommand, CanExecutePrevCommand);
      this.FinishCommand = new DelegateCommand<object>(ExecuteFinishCommand);
    }

    #endregion

    #region Helper Methods

    private void ExecuteNextCommand(object param)
    {
      int index = this.pages.IndexOf(this.Page);
      this.Page = this.pages[index + 1];
    }

    private bool CanExecuteNextCommand(object param)
    {
      if (this.Page == null)
        return false;

      int index = this.pages.IndexOf(this.Page);
      return index < (this.pages.Count - 1);
    }

    private void ExecutePrevCommand(object param)
    {
      int index = this.pages.IndexOf(this.Page);
      this.Page = this.pages[index - 1];
    }

    private bool CanExecutePrevCommand(object param)
    {
      if (this.Page == null)
        return false;

      int index = this.pages.IndexOf(this.Page);
      return index > 0;
    }

    private void ExecuteFinishCommand(object param)
    {
      Close(true);
    }

    private void UpdateCommands()
    {
      ((DelegateCommand<object>)NextCommand).RaiseCanExecuteChanged();
      ((DelegateCommand<object>)PrevCommand).RaiseCanExecuteChanged();
      ((DelegateCommand<object>)FinishCommand).RaiseCanExecuteChanged();
    }

    #endregion

    #region Public Methods

    /// <summary>
    /// Adds the page.
    /// </summary>
    /// <param name="page">The page.</param>
    public void AddPage(IWizardPageViewModel page)
    {
      this.pages.Add(page);
      if (this.Page == null)
        this.Page = page;
    }


    #endregion

    #region Public Properties

    /// <summary>
    /// Gets the next command.
    /// </summary>
    /// <value>The next command.</value>
    public ICommand NextCommand { get; private set; }

    /// <summary>
    /// Gets the prev command.
    /// </summary>
    /// <value>The prev command.</value>
    public ICommand PrevCommand { get; private set; }

    /// <summary>
    /// Gets the finish command.
    /// </summary>
    /// <value>The finish command.</value>
    public ICommand FinishCommand { get; private set; }


    /// <summary>
    /// Gets or sets the page
    /// </summary>
    public IWizardPageViewModel Page
    {
      get
      {
        return this.page;
      }
      set
      {
        if (this.page == value)
          return;

        OnPropertyChanging("Page");
        this.page = value;
        OnPropertyChanged("Page");

        if (this.page != null)
          this.Title = this.page.Title;

        UpdateCommands();
      }
    }

    #endregion
  }

  /// <summary>
  /// An image wizard page
  /// </summary>
  public class ImageWizardPageViewModel : ViewModelBase, IWizardPageViewModel
  {
    #region Fields

    private string title;
    private string message;
    private ImageSource image;

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the title
    /// </summary>
    public string Title
    {
      get
      {
        return this.title;
      }
      set
      {
        if (this.title == value)
          return;

        OnPropertyChanging("Title");
        this.title = value;
        OnPropertyChanged("Title");
      }
    }

    /// <summary>
    /// Gets or sets the message
    /// </summary>
    public string Message
    {
      get
      {
        return this.message;
      }
      set
      {
        if (this.message == value)
          return;

        OnPropertyChanging("Message");
        this.message = value;
        OnPropertyChanged("Message");
      }
    }

    /// <summary>
    /// Gets or sets the image
    /// </summary>
    public ImageSource Image
    {
      get
      {
        return this.image;
      }
      set
      {
        if (this.image == value)
          return;

        OnPropertyChanging("Image");
        this.image = value;
        OnPropertyChanged("Image");
      }
    }

    #endregion
  }

}
